#pragma once
#include <iostream>
#include <mutex>
#include <thread>

namespace lixixi {
	//持有权转移
	template<class T>
	class auto_ptr {
	public:
		auto_ptr(T* ptr) :_ptr(ptr) {
			std::cout << "构造:" << _ptr << std::endl;
		}

		auto_ptr(auto_ptr& ptr) :_ptr(ptr._ptr) {
			ptr._ptr = nullptr;
		}

		auto_ptr& operator=(auto_ptr& ptr)
		{
			if (ptr._ptr != _ptr)
			{
				delete _ptr;
				_ptr = ptr._ptr;
				ptr._ptr = nullptr;
			}
			return *this;
		}

		T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return _ptr;
		}

		~auto_ptr()
		{
			std::cout << "Delete:" << _ptr << std::endl;
			delete _ptr;
		}

	private:
		T* _ptr;
	};

	//不允许赋值及拷贝构造
	template<class T>
	class unique_ptr {
	public:
		unique_ptr(T* ptr) :_ptr(ptr) {}

		unique_ptr(unique_ptr& ptr) = delete;

		unique_ptr& operator=(unique_ptr& ptr) = delete;

		T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return &_ptr;
		}

		~unique_ptr()
		{
			std::cout << "Delete:" << _ptr << std::endl;
			delete _ptr;
		}
	private:
		T* _ptr;
	};

	//计数引用
	template<class T>
	class shared_ptr {
	public:
		shared_ptr(T* ptr) 
			:_ptr(ptr)
			, _count(new int(0)) 
			, _mtx(new std::mutex) { add_count(); }

		shared_ptr(shared_ptr& sp):_ptr(sp._ptr),_count(sp._count),_mtx(sp._mtx)
		{
			add_count();
		}

		shared_ptr& operator=(shared_ptr& sp)
		{
			if (sp._ptr != _ptr)
			{
				release();
				_ptr = sp._ptr;
				_count = sp._count;
				add_count();
			}
			return *this;
		}

		T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return _ptr;
		}

		void add_count()
		{
			_mtx->lock();
			++*_count;
			_mtx->unlock();
		}

		void release()
		{
			bool flag = false;
			_mtx->lock();
			if (--*_count == 0)
			{
				delete _count;
				delete _ptr;
				std::cout << "回收资源" << std::endl;
				flag = true;
			}
			_mtx->unlock();
			if(flag)
				delete _mtx;
			return;
		}

		~shared_ptr()
		{
			release();
		}
	private:
		T* _ptr;
		int* _count;
		std::mutex* _mtx;
	};
}